﻿using Assets.Scripts.Enums;
using UnityEngine;
using UnityEngine.UI;

namespace Assets.Scripts.UI
{
    public class UiRoot:MonoBehaviour
    {
        public delegate void KeyDownHandler(object sender, KeyEventArgs e);
        public event KeyDownHandler KeyDown;
        public event KeyDownHandler KeyUp;

        [HideInInspector]
        public Transform Root { get; private set; }
        [HideInInspector]
        public Transform FixedRoot { get; private set; }
        [HideInInspector]
        public Transform NormalRoot { get; private set; }
        [HideInInspector]
        public Transform PopUpRoot { get; private set; }
        [HideInInspector]
        public Camera Camera { get; private set; }

        public static UiRoot Get
        {
            get
            {
                if (_instance == null)
                    InitRoot();
                return _instance;
            }
        }

        public void Log(string str)
        {
            Debug.Log(str);
        }

        private void OnGUI()
        {
            OnKeyDown();
            OnKeyUp();
        }

        void OnKeyDown()
        {
            if (Event.current.rawType == EventType.KeyDown && Event.current.keyCode != KeyCode.None)
            {
                Event.current.Use();
                var keyData = UnityKeyTranslator.ToKeyData(Event.current.modifiers, Event.current.keyCode);
                var keyArgs = new KeyEventArgs(keyData);
                KeyDown?.Invoke(this, keyArgs);
            }
        }

        void OnKeyUp()
        {
            if (Event.current.rawType == EventType.KeyUp && Event.current.keyCode != KeyCode.None)
            {
                Event.current.Use();
                var keyData = UnityKeyTranslator.ToKeyData(Event.current.modifiers, Event.current.keyCode);
                var keyArgs = new KeyEventArgs(keyData);
                KeyUp?.Invoke(this, keyArgs);
            }
        }

        static void InitRoot()
        {
            GameObject go = new GameObject("UIRoot") {layer = LayerMask.NameToLayer("UI")};
            _instance = go.AddComponent<UiRoot>();

            Canvas can = go.AddComponent<Canvas>();
            can.renderMode = RenderMode.ScreenSpaceCamera;
            can.pixelPerfect = true;

            go.AddComponent<GraphicRaycaster>();
            _instance.Root = go.transform;

            GameObject camObj = new GameObject("UICamera") {layer = LayerMask.NameToLayer("UI")};
            camObj.transform.parent = go.transform;
            camObj.transform.localPosition = new Vector3(0, 0, -100f);
            Camera cam = camObj.AddComponent<Camera>();
            cam.clearFlags = CameraClearFlags.Depth;
            cam.orthographic = true;
            cam.farClipPlane = 200f;
            can.worldCamera = cam;
            cam.cullingMask = 1 << 5;
            cam.nearClipPlane = -50f;
            cam.farClipPlane = 50f;

            _instance.Camera = cam;

            CanvasScaler scaler = go.AddComponent<CanvasScaler>();
            scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
            scaler.referenceResolution = new Vector2(800f, 600f);
            scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.Expand;

            foreach (SubRoot type in System.Enum.GetValues(typeof(SubRoot)))
            {
                CreateSubCanvasForRoot(go.transform,type);
            }

        }

        static void CreateSubCanvasForRoot(Transform root, SubRoot name)
        {
            GameObject go = new GameObject("canvas");
            go.transform.SetParent(root);
            go.transform.localScale = Vector3.one;
            go.name = name.ToString();
            go.layer = LayerMask.NameToLayer("UI");

            RectTransform rect = go.AddComponent<RectTransform>();
            rect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, 0, 0);
            rect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 0, 0);
            rect.anchorMin = Vector2.zero;
            rect.anchorMax = Vector2.one;
        }

        private static UiRoot _instance;

    }
}
